<template>
  <el-card
    style="margin-top: 10px; box-shadow: none; border: none"
    :body-style="{ paddingBottom: '15px', paddingTop: 0 }"
  >
    <lc-st-operator
      v-if="operator !== 'none'"
      :column="dropdown"
      v-bind="operator"
      @change="change"
      @add="add"
      @refresh="reset()"
      @del="del"
    />
    <el-table
      :id="id"
      ref="tableRef"
      style="width: 100%"
      :row-key="'id'"
      :border="!noBorder"
      :height="height"
      :max-height="maxHeight"
      :show-header="!noShowHeader"
      :stripe="!noStripe"
      :size="size"
      :data="data.tableData"
      :empty-text="emptyText"
      :row-class-name="rowClassName"
      @current-change="currentChange ?? null"
      @selection-change="selectionChange"
      @sort-change="sortChange"
      @expand-change="expandChange"
      :lazy="lazy"
      :load="load"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      :default-sort="defaultSort"
      :highlight-current-row="highlightCurrentRow"
      v-loading="loading"
      :key="reload"
    >
      <el-table-column v-if="expand" type="expand">
        <template #default="props">
          <slot name="expand" :row="props.row" :index="props.$index" />
        </template>
      </el-table-column>
      <template v-for="(c, i) in column" :key="i">
        <component
          v-if="acls.canAbility(c.acl) && noHidden(c)"
          :is="ST_COLLECTION[getType(c)]"
          v-bind="c"
        />
      </template>
    </el-table>
    <lc-st-pagination
      v-if="!noEnabledPage"
      v-model:pi="pageParams.pi"
      v-model:ps="pageParams.ps"
      :total="total"
      :hide-on-single-page="pagesParams.hideOnSinglePage"
      :showJumper="pagesParams.showJumper"
      @change="reset()"
    />
  </el-card>
</template>

<script lang="ts" setup name="lc-st-">
import { reactive, ref, onMounted, computed, toRaw, provide } from "vue";
import { ST_COLLECTION } from "./index";
import type { CheckboxValueType, TableInstance } from "element-plus";
import LcStPagination from "./st-pagination/st-pagination.vue";
import LcStOperator from "./st-operator/st-operator.vue";
import {
  ITableOptions,
  ITableColumn,
  TPages,
  ColumnKeys,
  TOporaterOption
} from "./interface";
import { Http } from "@/core/api/http.service";
import { NzSafeAny } from "../sf/type";
import { Subject } from "rxjs";
import { useAclHooks } from "@/core/pinia/store/acl.store";
/** 初始化父传子的数据*/
const props = withDefaults(defineProps<ITableOptions>(), {
  lazy: (props: ITableOptions) => props.lazy,
  load: (props: ITableOptions) => props.lazy,
  data: (props: ITableOptions) => props.data || [],
  column: (props: ITableOptions) => props.column || [],
  rowClassName: (props: ITableOptions) => props.rowClassName,
  currentChange: (props: ITableOptions) => props.currentChange,
  selectionChange: (props: ITableOptions) => props.selectionChange,
  defaultSort: (props: ITableOptions) => props.defaultSort,
  height: (props: ITableOptions) => props.height,
  maxHeight: (props: ITableOptions) => props.maxHeight,
  noStripe: (props: ITableOptions) => props.noStripe,
  noBorder: (props: ITableOptions) => props.noBorder,
  size: (props: ITableOptions) => props.size || "default",
  fit: (props: ITableOptions) => props.fit,
  pi: (props: ITableOptions) => props.pi || 1,
  ps: (props: ITableOptions) => props.ps || 10,
  parent: (props: ITableOptions) => props.parent,
  noShowHeader: (props: ITableOptions) => props.noShowHeader,
  highlightCurrentRow: (props: ITableOptions) => props.highlightCurrentRow,
  emptyText: (props: ITableOptions) => props.emptyText || "暂无数据",
  operator: (props: ITableOptions) => props.operator || ({} as TOporaterOption),
  expandChange: (props: ITableOptions) => props.expandChange,
  pages: (props: ITableOptions) => props.pages || {},
  expand: (props: ITableOptions) => props.expand,
  noEnabledPage: (props: ITableOptions) => props.noEnabledPage
});
const id = ref(Date.now());
const reload = ref();
const searchQuery = ref({});
const loading = ref(false);
const tableRef = ref<TableInstance>();
const pageParams = reactive({
  pi: props.pi,
  ps: props.ps
});
const { prop, order } = props.defaultSort || {};
const sort = reactive({
  sortBy: prop && order ? [prop] : [],
  isAsc: prop && order ? [order === "ascending" ? true : false] : []
});
const total = ref(0);
const data = reactive({
  tableData: []
});

const pagesParams = reactive<TPages>({
  pageSizes: [10, 20, 50, 100],
  showJumper: true,
  hideOnSinglePage: false,
  totalKey: "total",
  currentPage: "pi",
  record: "list",
  limit: "ps",
  ...props.pages
});
const getType = (c: ITableColumn) => {
  return c?.buttons?.length ? "handler" : c.type || "column";
};
const acls = useAclHooks();
const noHidden = computed(() => {
  return (c: ITableColumn) => {
    if (c.hidden) {
      return false;
    }
    return c.iff ? c.iff(c) : true;
  };
});
const dropdown = ref<ColumnKeys[]>(
  props.column.map(r => {
    return {
      label:
        r.label ||
        (r.type === "selection"
          ? "勾选框"
          : r.type === "index"
          ? "序号"
          : r.prop),
      acl: r.acl,
      value: r.prop,
      type: r.type,
      checked: !r.hidden
    };
  })
);
/** 列选择事件 */
const change = (check: CheckboxValueType, { value, type }: ColumnKeys) => {
  const column = props.column.find(c =>
    value ? value === c.prop : type ? type === c.type : !c.type && !c.prop
  );
  if (column) {
    column.hidden = !check;
    reload.value = Math.random();
  }
};
const sortChange = ({ prop, order }: { prop: string; order: string }) => {
  const index = sort.sortBy.indexOf(prop);
  if (index > -1) {
    if (!order) {
      sort.sortBy = [];
      sort.isAsc = [];
    } else {
      sort.isAsc[index] = order === "ascending" ? true : false;
    }
  } else if (order) {
    sort.sortBy = [prop];
    sort.isAsc = [order === "ascending" ? true : false];
  }
  reset();
};
const addEvent = new Subject<TableInstance>();
/** 新增事件 */
const add = () => {
  if (addEvent.observed) {
    addEvent.next(tableRef.value);
  } else {
    console.log("你想新增了吗？");
  }
};
/** 删除事件 */
const delEvent = new Subject<string[]>();
const del = () => {
  const data = tableRef.value.getSelectionRows();
  if (delEvent.observed) {
    delEvent.next(toRaw(data).map((r: { id: string }) => r?.id));
  } else {
    console.log("你想删除了吗？");
  }
};
const url = ref(props.data);
const reset = (query?: Record<string, NzSafeAny>) => {
  if (query) {
    searchQuery.value = query;
  }
  const params = {
    [pagesParams.currentPage]: pageParams.pi,
    [pagesParams.limit]: pageParams.ps,
    ...(searchQuery.value || {})
  };
  if (sort.sortBy.length) {
    params["sortBy"] = sort.sortBy.join(",");
    params["isAsc"] = sort.isAsc.join(",");
  }
  if (url.value) {
    if (typeof url.value === "string") {
      loading.value = true;
      Http.of()
        .get(url.value, params)
        .then(res => {
          total.value = res?.[pagesParams.totalKey] || 0;
          data.tableData = res?.[pagesParams.record] || [];
          if (props.expand) {
            hidenExpand();
          }
        })
        .catch()
        .finally(() => (loading.value = false));
    } else {
      data.tableData = url.value || [];
      if (props.expand) {
        hidenExpand();
      }
    }
  }
};

const setData = (path: string) => {
  url.value = path;
  reset();
};

const resetChild = (data: NzSafeAny) => {
  tableRef.value.toggleRowExpansion(data, false);
  setTimeout(() => {
    tableRef.value.toggleRowExpansion(data, true);
  }, 10);
};

const hidenExpand = () => {
  if (data.tableData?.length) {
    data.tableData.forEach((row: NzSafeAny, rowIndex: number) => {
      const el = document.getElementById(id.value as unknown as string);
      if (el && row?.isLeaf) {
        const item = el.querySelector("tbody");
        if (item) {
          let timer = setTimeout(() => {
            const childEl = [
              ...((item.children as unknown as HTMLElement[]) || [])
            ]?.[rowIndex];
            if (childEl?.firstElementChild && timer) {
              clearTimeout(timer);
              timer = null;
              childEl.firstElementChild.innerHTML = null;
            }
          }, 10);
        }
      }
    });
  }
};
onMounted(() => {
  const ok = props.onloadChildren
    ? props.onloadChildren(url.value as string)
    : true;
  if (ok) {
    reset();
  }
});
const params = {
  reset,
  setData,
  del: delEvent,
  add: addEvent,
  tableRef,
  resetChild
};
provide("st-intence", params);
defineExpose({
  reset,
  setData,
  del: delEvent,
  add: addEvent,
  tableRef,
  resetChild
});
</script>
<style>
.table-pagination {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  background-color: var(--ba-bg-color-overlay);
  padding: 13px 15px;
  justify-content: flex-end;
}
.el-table__header .cell {
  color: var(--el-text-color-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>
./interfaces ../sf/types
